package cn.y.operation.framework.mvc;

import cn.y.operation.application.core.entity.SysUser;
import cn.y.operation.framework.constants.Constants;
import cn.y.operation.framework.enums.ResponseMsgEnum;
import cn.y.operation.framework.page.PageDomain;
import cn.y.operation.framework.page.TableDataInfo;
import cn.y.operation.framework.page.TableSupport;
import cn.y.operation.framework.utils.dev.DateUtils;
import cn.y.operation.framework.utils.database.SqlUtils;
import cn.y.operation.framework.utils.dev.StringUtils;
import cn.y.operation.framework.utils.encryption.RegexUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;

import javax.servlet.http.HttpServletRequest;
import java.beans.PropertyEditorSupport;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.*;

/**
 * Controller 工具类
 *
 * @author 烨
 */
public abstract class BaseController {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    protected String forward(String url) {
        return "forward:" + url;
    }

    protected String redirect(String url) {
        return "redirect:" + url;
    }

    /**
     * 响应请求分页数据
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    protected TableDataInfo getDataTable(List<?> list) {
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(ResponseMsgEnum.SUCCESS.getCode());
        rspData.setData(list);
        rspData.setCount(new PageInfo(list).getTotal());
        return rspData;
    }

    protected ResponseMsg returnResult(String result) {
        return StringUtils.isEmpty(result) ? success() : error(result);
    }

    protected ResponseMsg data(Object data) {
        return ResponseMsg.data(data);
    }

    protected ResponseMsg success() {
        return new ResponseMsg(ResponseMsgEnum.SUCCESS);
    }

    protected ResponseMsg success(String string) {
        return ResponseMsg.success(string);
    }

    protected ResponseMsg success(ResponseMsgEnum responseMsgEnum) {
        return new ResponseMsg(responseMsgEnum);
    }

    protected ResponseMsg error() {
        return new ResponseMsg(ResponseMsgEnum.FAIL);
    }

    protected ResponseMsg error(String string) {
        return ResponseMsg.error(string);
    }

    protected ResponseMsg error(ResponseMsgEnum responseMsgEnum) {
        return new ResponseMsg(responseMsgEnum);
    }

    /**
     * 设置请求分页数据
     */
    protected void startPage() {
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();
        if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) {
            String orderBy = SqlUtils.escapeOrderBySql(pageDomain.getOrderBy());
            PageHelper.startPage(pageNum, pageSize, orderBy);
        }
    }

    /**
     * 初始化数据绑定
     * 1. 将所有传递进来的String进行HTML编码，防止XSS攻击
     * 2. 将字段中Date类型转换为String类型
     * 3. 处理int double等类型的数据绑定
     */
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        // String类型转换，将所有传递进来的String进行HTML编码，防止XSS攻击
        binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                setValue(text == null ? null : RegexUtils.deleteHtmlTag(text.trim()));
            }

            @Override
            public String getAsText() {
                Object value = getValue();
                return value == null ? "" : value.toString();
            }
        });
        // Date 类型转换
        binder.registerCustomEditor(Date.class,
                new PropertyEditorSupport() {
                    @Override
                    public void setAsText(String text) {
                        try {
                            setValue(DateUtils.parseDate(text));
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                });
    }

    /**
     * 获取当前登录用户
     *
     * @return (SysUser) SecurityUtils.getSubject().getPrincipal()
     */
    protected SysUser getSessionUser() {
        return (SysUser) SecurityUtils.getSubject().getPrincipal();
    }

    /**
     * 获取当前登录用户id
     *
     * @return getSessionUser().getUserId()
     */
    protected int getSessionUserId() {
        return this.getSessionUser().getUserId().intValue();
    }

    /**
     * 文件下载
     */
    protected ResponseEntity<byte[]> renderSteam(byte[] bytes, String fileName) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        try {
            headers.setContentDispositionFormData("attachment", URLEncoder.encode(fileName, Constants.UTF8));
        } catch (UnsupportedEncodingException e) {
        }
        return new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
    }

    public String getIpAddress(HttpServletRequest request) {
        String ip = null;
        //X-Forwarded-For：Squid 服务代理
        String ipAddresses = request.getHeader("X-Forwarded-For");
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //Proxy-Client-IP：apache 服务代理
            ipAddresses = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //WL-Proxy-Client-IP：weblogic 服务代理
            ipAddresses = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //HTTP_CLIENT_IP：有些代理服务器
            ipAddresses = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //X-Real-IP：nginx服务代理
            ipAddresses = request.getHeader("X-Real-IP");
        }
        //有些网络通过多层代理，那么获取到的ip就会有多个，一般都是通过逗号（,）分割开来，并且第一个ip为客户端的真实IP
        if (ipAddresses != null && ipAddresses.length() != 0) {
            ip = ipAddresses.split(",")[0];
        }
        //还是不能获取到，最后再通过request.getRemoteAddr();获取
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}
